/*
Copyright (C) 2021-2025 Casa Xu (also Zhiyan Xu) from HIT

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

/*
 * LOS_FVAR.c
 *
 *  Created on: 2024年9月25日
 *      Author: 64435
 */

#include "LOS_FVAR.h"

/* 要从FRAM中读取的变量 FR = FRAM Variables */
//UTC时间，发射前设置好初值用于三轴对日，运行时每10s存储一次
uint32_t FR_UTC = 247536000;
uint8_t FR_UTC_SEL = 0;   //表示FR_UTC来自哪里，0表示取默认值，0XFF表示取自FRAM
//天线/遮光罩热刀使能
uint32_t FR_TKANTEN = 0XFFFFFFCB;
uint8_t FR_TKANTEN_SEL = 0;
//太阳翼热刀使能
uint32_t FR_TKSAEN = 0XFFFFFFCB;
uint8_t FR_TKSAEN_SEL = 0;
//模式切换阈值Mode Change Threshold
float FR_MCTR[20];
uint8_t FR_MCTR_SEL = 0;
//安装矩阵
float FR_MATSSY[9];
uint8_t FR_MATSSY_SEL = 0;
float FR_MATSSZ[9];
uint8_t FR_MATSSZ_SEL = 0;
float FR_MATYH50[9];
uint8_t FR_MATYH50_SEL = 0;
float FR_MATSUNS[9];
uint8_t FR_MATSUNS_SEL = 0;
float FR_MATMAGME[9];
uint8_t FR_MATMAGME_SEL = 0;
//星敏Y安装四元数
float FR_MQSSY[4];
uint8_t FR_MQSSY_SEL = 0;
//星敏Z安装四元数
float FR_MQSSZ[4];
uint8_t FR_MQSSZ_SEL = 0;
//磁力矩器最大磁矩
float FR_MGTMAX[6];
uint8_t FR_MGTMAX_SEL = 0;
//上电后是否进行延时
uint32_t FR_DELAYEN = 0XFFFFFFCB;
uint8_t FR_DELAYEN_SEL = 0;
//上电后的延时时间
uint32_t FR_DELAYDUR = 900;
uint8_t FR_DELAYDUR_SEL = 0;
//A B机标识
uint32_t FR_OBC = 0XAAAAAAAA;
uint8_t FR_OBC_SEL = 0;
//烧绳相关的
uint32_t FR_TKMAXCNT = 3; //烧绳次数上限
uint8_t FR_TKMAXCNT_SEL = 0;
uint32_t FR_TKDUR = 1; //持续时间s 
uint8_t FR_TKDUR_SEL = 0;
//GPS是否自动上电
uint32_t FR_GPSAUTO = 0XFFFFFFCB;
uint8_t FR_GPSAUTO_SEL = 0;
//磁强计补偿值
float FR_MAGCOMP[3] = {0, 0, 0};
uint8_t FR_MAGCOMP_SEL = 0;
//自动开数传设置，数组第0个元素为收不到指令的时间(s)，第二个元素为电压阈值(mV)
uint32_t FR_DTAUTO[2] = {43200, 11300};
uint8_t FR_DTAUTO_SEL = 0;

//遥测间隔时间(单位s),发四包遥测需要2s,间隔默认28s，保证30s发一次
uint16_t FR_TMInvTime = 0;
uint8_t FR_TMInvTime_SEL = 0;
//上电次数
uint32_t FR_BOOTCNT = 0;
//复位后运行在什么鸟地方
uint8_t FLASH_WHERE = 0X55;

/** @fn void LOS_FVAR_GetAllVAR()
*   @brief 读取FRAM中存储的所有数据，并将其赋值给相应的变量
*   @note 卫星刚上电时运行
*/
void LOS_FVAR_GetAllVAR()
{
    LOS_Time_Sec = LOS_FVAR_GetUTCFromFRAM();
    LOS_FVAR_GetTKANTENFromFRAM();
    LOS_FVAR_GetTKSAENFromFRAM();
    LOS_FVAR_GetMATSSYFromFRAM();
    LOS_FVAR_GetMATSSZFromFRAM();
    LOS_FVAR_GetMATYH50FromFRAM();
    LOS_FVAR_GetMATSUNSFromFRAM();
    LOS_FVAR_GetMATMAGMEFromFRAM();
    LOS_FVAR_GetMQSSYFromFRAM();
    LOS_FVAR_GetMQSSZFromFRAM();
    LOS_FVAR_GetMCTRFromFRAM();
    LOS_FVAR_GetMGTMAXFromFRAM();
    LOS_FVAR_GetDELAYENFromFRAM();
    LOS_FVAR_GetDELAYDURFromFRAM();
    LOS_FVAR_GetOBCFromFRAM();
    LOS_FVAR_GetTKMAXCNTFromFRAM();
    LOS_FVAR_GetTKDURFromFRAM();
    LOS_FVAR_GetGPSAUTOFromFRAM();
    LOS_FVAR_GetMAGCOMPFromFRAM();
    LOS_FVAR_GetDTAUTOFromFRAM();
    memcpy(&FLASH_WHERE,0xF0210000,1);
}

/** @fn void LOS_FVAR_ModifyFRUTC(uint32_t* UTC)
*   @brief 修改FRAM中的UTC值
*   @param[in] UTC UTC时间
*   @note 该函数除了会改变FRAM中的UTC时间，还会更新FR_UTC的值
*/
void LOS_FVAR_ModifyFRUTC(uint32_t UTC)
{
    static uint8_t UTC_Bytes[36]; //存放编码后的数据
    static int ret_dcd = 0;
    uint32_t utcbuf = UTC;

    LOS_W25Q64S_SectorErase(ADDR_FR_UTC);
    memcpy(UTC_Bytes, &utcbuf, 4);
    encode_rs(UTC_Bytes, &UTC_Bytes[4], NN - NROOTS - 4);
    LOS_W25Q64S_PageWrite(ADDR_FR_UTC, UTC_Bytes, 4 + NROOTS);
    LOS_FVAR_GetUTCFromFRAM();
}

/** @fn uint32_t LOS_FVAR_GetUTCFromFRAM(uint32_t UTC)
*   @brief 读取FRAM中预存的UTC时间
*   @note 该函数从FRAM中读取UTC时间，该值会存入FR_UTC，并通过返回值传递
*/
uint32_t LOS_FVAR_GetUTCFromFRAM()
{
    static uint8_t UTC_Bytes[36]; //存放解码后的数据
    LOS_W25Q64S_ReadData(ADDR_FR_UTC, UTC_Bytes, 36);
    if(decode_rs(UTC_Bytes, NULL, 0, NN - NROOTS - 4) >= 0) //解码成功
    {
        memcpy(&FR_UTC, UTC_Bytes, 4);
        FR_UTC_SEL = FROM_FRAM;
    }
    else //解码失败
    {
        FR_UTC = 247536000;
        FR_UTC_SEL = FROM_DEFAULT;
    }
    return FR_UTC;
}

/** @fn void LOS_FVAR_ModifyTKANTEN(uint32_t key)
*   @brief 修改FRAM中FR_TKANTEN的值
*   @param[in] key 解锁热刀密钥
*   @note 只有输入的是0XABED5CFA时，飞行程序中才会解锁热刀
*/
void LOS_FVAR_ModifyTKANTEN(uint32_t key)
{
    static uint8_t KEY_Bytes[36]; //存放编码后的数据
    static int ret_dcd = 0;
    uint32_t tkbuf = key;

    LOS_W25Q64_SectorErase(ADDR_FR_TKANTEN);
    memcpy(KEY_Bytes, &tkbuf, 4);
    encode_rs(KEY_Bytes, &KEY_Bytes[4], NN - NROOTS - 4);
    LOS_W25Q64_PageWrite(ADDR_FR_TKANTEN, KEY_Bytes, 4 + NROOTS);
    LOS_FVAR_GetTKANTENFromFRAM();
}

/** @fn uint32_t LOS_FVAR_GetTKANTENFromFRAM()
*   @brief 读取FRAM中预存的天线热刀密钥
*   @note 该函数从FRAM中读取天线热刀密钥，该值会存入FR_TKANTEN
*/
uint32_t LOS_FVAR_GetTKANTENFromFRAM()
{
    static uint8_t KEY_Bytes[36]; //存放解码后的数据
    LOS_W25Q64_ReadData(ADDR_FR_TKANTEN, KEY_Bytes, 36);
    if(decode_rs(KEY_Bytes, NULL, 0, NN - NROOTS - 4) >= 0) //解码成功
    {
        memcpy(&FR_TKANTEN, KEY_Bytes, 4);
        FR_TKANTEN_SEL = FROM_FRAM;
    }
    else //解码失败，则默认解锁
    {
        FR_TKANTEN = 0XABED5CFA;
        FR_TKANTEN_SEL = FROM_DEFAULT;
    }
    return FR_TKANTEN;
}

/** @fn void LOS_FVAR_ModifyTKSAEN(uint32_t key)
*   @brief 修改FRAM中FR_TKSAEN的值
*   @param[in] key 解锁热刀密钥
*   @note 只有输入的是0XABED5CFA时，飞行程序中才会解锁热刀
*/
void LOS_FVAR_ModifyTKSAEN(uint32_t key)
{
    static uint8_t KEY_Bytes[36]; //存放编码后的数据
    static int ret_dcd = 0;
    uint32_t tkbuf = key;

    LOS_W25Q64_SectorErase(ADDR_FR_TKSAEN);
    memcpy(KEY_Bytes, &tkbuf, 4);
    encode_rs(KEY_Bytes, &KEY_Bytes[4], NN - NROOTS - 4);
    LOS_W25Q64_PageWrite(ADDR_FR_TKSAEN, KEY_Bytes, 4 + NROOTS);
    LOS_FVAR_GetTKSAENFromFRAM();
}

/** @fn uint32_t LOS_FVAR_GetTKSAENFromFRAM()
*   @brief 读取FRAM中预存的太阳翼热刀密钥
*   @note 该函数从FRAM中读取太阳翼热刀密钥，该值会存入FR_TKSAEN
*/
uint32_t LOS_FVAR_GetTKSAENFromFRAM()
{
    static uint8_t KEY_Bytes[36]; //存放解码后的数据
    static int ret_dcd = 0;
    LOS_W25Q64_ReadData(ADDR_FR_TKSAEN, KEY_Bytes, 36);
    ret_dcd = decode_rs(KEY_Bytes, NULL, 0, NN - NROOTS - 4);
    if(ret_dcd >= 0) //解码成功
    {
        memcpy(&FR_TKSAEN, KEY_Bytes, 4);
        FR_TKSAEN_SEL = FROM_FRAM;
    }
    else //解码失败，则默认解锁
    {
        FR_TKSAEN = 0XABED5CFA;
        FR_TKSAEN_SEL = FROM_DEFAULT;
    }
    return FR_TKSAEN;
}

/** @fn void LOS_FVAR_ModifyDELAYEN(uint32_t key)
*   @brief 修改FRAM中FR_DELAYEN的值
*   @param[in] key 开启飞行程序延时密钥
*   @note 只有输入的是0XABED5CFA时，飞行程序才会延时
*/
void LOS_FVAR_ModifyDELAYEN(uint32_t key)
{
    static uint8_t KEY_Bytes[36]; //存放编码后的数据
    static int ret_dcd = 0;
    uint32_t tkbuf = key;

    LOS_W25Q64_SectorErase(ADDR_FR_DELAYEN);
    memcpy(KEY_Bytes, &tkbuf, 4);
    encode_rs(KEY_Bytes, &KEY_Bytes[4], NN - NROOTS - 4);
    LOS_W25Q64_PageWrite(ADDR_FR_DELAYEN, KEY_Bytes, 4 + NROOTS);
    LOS_FVAR_GetDELAYENFromFRAM();
}

/** @fn uint32_t LOS_FVAR_GetDELAYENFromFRAM()
*   @brief 读取FRAM中预存的开启飞行程序延时状态
*   @note 该函数从FRAM中读取太开启飞行程序延时状态，该值会存入FR_DELAYEN
*/
uint32_t LOS_FVAR_GetDELAYENFromFRAM()
{
    static uint8_t KEY_Bytes[36]; //存放解码后的数据
    static int ret_dcd = 0;
    LOS_W25Q64_ReadData(ADDR_FR_DELAYEN, KEY_Bytes, 36);
    ret_dcd = decode_rs(KEY_Bytes, NULL, 0, NN - NROOTS - 4);
    if(ret_dcd >= 0) //解码成功
    {
        memcpy(&FR_DELAYEN, KEY_Bytes, 4);
        FR_DELAYEN_SEL = FROM_FRAM;
    }
    else //解码失败，则默认开启
    {
        FR_DELAYEN = 0XABED5CFA;
        FR_DELAYEN_SEL = FROM_DEFAULT;
    }
    return FR_DELAYEN;
}

/** @fn void LOS_FVAR_ModifyDELAYDUR(uint32_t key)
*   @brief 修改FRAM中FR_DELAYDUR的值
*   @param[in] key 修改飞行程序延时时间
*   @note 
*/
void LOS_FVAR_ModifyDELAYDUR(uint32_t time)
{
    static uint8_t KEY_Bytes[36]; //存放编码后的数据
    static int ret_dcd = 0;
    uint32_t tkbuf = time;

    LOS_W25Q64_SectorErase(ADDR_FR_DELAYDUR);
    memcpy(KEY_Bytes, &tkbuf, 4);
    encode_rs(KEY_Bytes, &KEY_Bytes[4], NN - NROOTS - 4);
    LOS_W25Q64_PageWrite(ADDR_FR_DELAYDUR, KEY_Bytes, 4 + NROOTS);
    LOS_FVAR_GetDELAYDURFromFRAM();
}

/** @fn uint32_t LOS_FVAR_GetDELAYDURFromFRAM()
*   @brief 读取FRAM中预存的飞行程序延时时间
*   @note 该函数从FRAM中读取飞行程序延时时间，该值会存入FR_DELAYDUR
*/
uint32_t LOS_FVAR_GetDELAYDURFromFRAM()
{
    static uint8_t KEY_Bytes[36]; //存放解码后的数据
    static int ret_dcd = 0;
    LOS_W25Q64_ReadData(ADDR_FR_DELAYDUR, KEY_Bytes, 36);
    ret_dcd = decode_rs(KEY_Bytes, NULL, 0, NN - NROOTS - 4);
    if(ret_dcd >= 0) //解码成功
    {
        memcpy(&FR_DELAYDUR, KEY_Bytes, 4);
        FR_DELAYDUR_SEL = FROM_FRAM;
    }
    else //解码失败，则默认开启
    {
        FR_DELAYDUR = 900;
        FR_DELAYDUR_SEL = FROM_DEFAULT;
    }
    return FR_DELAYDUR;
}

/** @fn void LOS_FVAR_ModifyOBC(uint32_t key)
*   @brief 修改FRAM中FR_OBC的值
*   @param[in] key 
*   @note 
*/
void LOS_FVAR_ModifyOBC(uint32_t obc)
{
    static uint8_t KEY_Bytes[36]; //存放编码后的数据
    static int ret_dcd = 0;
    uint32_t tkbuf = obc;

    LOS_W25Q64_SectorErase(ADDR_FR_OBC);
    memcpy(KEY_Bytes, &tkbuf, 4);
    encode_rs(KEY_Bytes, &KEY_Bytes[4], NN - NROOTS - 4);
    LOS_W25Q64_PageWrite(ADDR_FR_OBC, KEY_Bytes, 4 + NROOTS);
    LOS_FVAR_GetOBCFromFRAM();
}

/** @fn uint32_t LOS_FVAR_GetOBCFromFRAM()
*   @brief 读取FRAM中的当班机状态
*   @note 该函数从FRAM中读取当班机状态，该值会存入FR_OBC
*/
uint32_t LOS_FVAR_GetOBCFromFRAM()
{
    static uint8_t KEY_Bytes[36]; //存放解码后的数据
    static int ret_dcd = 0;
    LOS_W25Q64_ReadData(ADDR_FR_OBC, KEY_Bytes, 36);
    ret_dcd = decode_rs(KEY_Bytes, NULL, 0, NN - NROOTS - 4);
    if(ret_dcd >= 0) //解码成功
    {
        memcpy(&FR_OBC, KEY_Bytes, 4);
        FR_OBC_SEL = FROM_FRAM;
        if (FR_OBC == 0XBBBBBBBB)
        {
            LOS_CPU = 0XBB;
        }
        else
        {
            LOS_CPU = 0XAA;
        }
    }
    else //解码失败，则默认A机
    {
        FR_OBC = 0XAAAAAAAA;
        LOS_CPU = 0XAA;
        FR_OBC_SEL = FROM_DEFAULT;
    }
    return FR_OBC;
}


/** @fn void LOS_FVAR_ModifyMATSSY(float* value)
*   @brief 修改FRAM中FR_MATSSY星敏Y安装矩阵的值
*   @param[in] value 指向上注安装矩阵缓冲区的指针
*   @note 
*/
void LOS_FVAR_ModifyMATSSY(float* value)
{
    static uint8_t KEY_Bytes[68]; //存放编码后的数据
    static int ret_dcd = 0;

    LOS_W25Q64_SectorErase(ADDR_FR_MATSSY);
    memcpy(KEY_Bytes, value, 36);
    encode_rs(KEY_Bytes, &KEY_Bytes[36], NN - NROOTS - 36);
    LOS_W25Q64_PageWrite(ADDR_FR_MATSSY, KEY_Bytes, 36 + NROOTS);
    LOS_FVAR_GetMATSSYFromFRAM();
}

/** @fn void LOS_FVAR_GetMATSSYFromFRAM()
*   @brief 读取FRAM中预存的星敏Y安装矩阵
*   @note 该函数从FRAM中读取星敏Y安装矩阵，该值会存入FR_MATSSY
*/
void LOS_FVAR_GetMATSSYFromFRAM()
{
    static uint8_t KEY_Bytes[68]; //存放解码后的数据
    static int ret_dcd = 0;
    LOS_W25Q64_ReadData(ADDR_FR_MATSSY, KEY_Bytes, 68);
    ret_dcd = decode_rs(KEY_Bytes, NULL, 0, NN - NROOTS - 36);
    if(ret_dcd >= 0 && ret_dcd <= 8) //解码成功
    {
        memcpy(FR_MATSSY, KEY_Bytes, 36);
        FR_MATSSY_SEL = FROM_FRAM;
    }
    else //解码失败，则用默认值
    {
        FR_MATSSY[0] = -1;
        FR_MATSSY[1] = 0;
        FR_MATSSY[2] = 0;
        FR_MATSSY[3] = 0;
        FR_MATSSY[4] = 0;
        FR_MATSSY[5] = -1;
        FR_MATSSY[6] = 0;
        FR_MATSSY[7] = -1;
        FR_MATSSY[8] = 0;
        FR_MATSSY_SEL = FROM_DEFAULT;
    }
}


/** @fn void LOS_FVAR_ModifyMATSSZ(float* value)
*   @brief 修改FRAM中FR_MATSSZ星敏Z安装矩阵的值
*   @param[in] value 指向上注安装矩阵缓冲区的指针
*   @note 
*/
void LOS_FVAR_ModifyMATSSZ(float* value)
{
    static uint8_t KEY_Bytes[68]; //存放编码后的数据
    static int ret_dcd = 0;

    LOS_W25Q64_SectorErase(ADDR_FR_MATSSZ);
    memcpy(KEY_Bytes, value, 36);
    encode_rs(KEY_Bytes, &KEY_Bytes[36], NN - NROOTS - 36);
    LOS_W25Q64_PageWrite(ADDR_FR_MATSSZ, KEY_Bytes, 36 + NROOTS);
    LOS_FVAR_GetMATSSZFromFRAM();
}

/** @fn void LOS_FVAR_GetMATSSZFromFRAM()
*   @brief 读取FRAM中预存的星敏Z安装矩阵
*   @note 该函数从FRAM中读取星敏Z安装矩阵，该值会存入FR_MATSSZ
*/
void LOS_FVAR_GetMATSSZFromFRAM()
{
    static uint8_t KEY_Bytes[68]; //存放解码后的数据
    static int ret_dcd = 0;
    LOS_W25Q64_ReadData(ADDR_FR_MATSSZ, KEY_Bytes, 68);
    ret_dcd = decode_rs(KEY_Bytes, NULL, 0, NN - NROOTS - 36);
    if(ret_dcd >= 0 && ret_dcd <= 8) //解码成功
    {
        memcpy(FR_MATSSZ, KEY_Bytes, 36);
        FR_MATSSZ_SEL = FROM_FRAM;
    }
    else //解码失败，则用默认值
    {
        FR_MATSSZ[0] = -1;
        FR_MATSSZ[1] = 0;
        FR_MATSSZ[2] = 0;
        FR_MATSSZ[3] = 0;
        FR_MATSSZ[4] = 1;
        FR_MATSSZ[5] = 0;
        FR_MATSSZ[6] = 0;
        FR_MATSSZ[7] = 0;
        FR_MATSSZ[8] = -1;
        FR_MATSSZ_SEL = FROM_DEFAULT;
    }
}

/** @fn void LOS_FVAR_ModifyMATYH50(float* value)
*   @brief 修改FRAM中FR_MATYH50光纤陀螺安装矩阵的值
*   @param[in] value 指向上注安装矩阵缓冲区的指针
*   @note 
*/
void LOS_FVAR_ModifyMATYH50(float* value)
{
    static uint8_t KEY_Bytes[68]; //存放编码后的数据
    static int ret_dcd = 0;

    LOS_W25Q64_SectorErase(ADDR_FR_MATYH50);
    memcpy(KEY_Bytes, value, 36);
    encode_rs(KEY_Bytes, &KEY_Bytes[36], NN - NROOTS - 36);
    LOS_W25Q64_PageWrite(ADDR_FR_MATYH50, KEY_Bytes, 36 + NROOTS);
    LOS_FVAR_GetMATYH50FromFRAM();
}

/** @fn void LOS_FVAR_GetMATYH50FromFRAM()
*   @brief 读取FRAM中预存的光纤陀螺安装矩阵
*   @note 该函数从FRAM中读取光纤陀螺安装矩阵，该值会存入FR_MATYH50
*/
void LOS_FVAR_GetMATYH50FromFRAM()
{
    static uint8_t KEY_Bytes[68]; //存放解码后的数据
    static int ret_dcd = 0;
    LOS_W25Q64_ReadData(ADDR_FR_MATYH50, KEY_Bytes, 68);
    ret_dcd = decode_rs(KEY_Bytes, NULL, 0, NN - NROOTS - 36);
    if(ret_dcd >= 0 && ret_dcd <= 8) //解码成功
    {
        memcpy(FR_MATYH50, KEY_Bytes, 36);
        FR_MATYH50_SEL = FROM_FRAM;
    }
    else //解码失败，则用默认值
    {
        FR_MATYH50[0] = 0;
        FR_MATYH50[1] = 1;
        FR_MATYH50[2] = 0;
        FR_MATYH50[3] = 1;
        FR_MATYH50[4] = 0;
        FR_MATYH50[5] = 0;
        FR_MATYH50[6] = 0;
        FR_MATYH50[7] = 0;
        FR_MATYH50[8] = -1;
        FR_MATYH50_SEL = FROM_DEFAULT;
    }
}

/** @fn void LOS_FVAR_ModifyMATSUNS(float* value)
*   @brief 修改FRAM中FR_MATSUNS太敏安装矩阵的值
*   @param[in] value 指向上注安装矩阵缓冲区的指针
*   @note 
*/
void LOS_FVAR_ModifyMATSUNS(float* value)
{
    static uint8_t KEY_Bytes[68]; //存放编码后的数据
    static int ret_dcd = 0;

    LOS_W25Q64_SectorErase(ADDR_FR_MATSUNS);
    memcpy(KEY_Bytes, value, 36);
    encode_rs(KEY_Bytes, &KEY_Bytes[36], NN - NROOTS - 36);
    LOS_W25Q64_PageWrite(ADDR_FR_MATSUNS, KEY_Bytes, 36 + NROOTS);
    LOS_FVAR_GetMATSUNSFromFRAM();
}

/** @fn void LOS_FVAR_GetMATSUNSFromFRAM()
*   @brief 读取FRAM中预存的太敏安装矩阵
*   @note 该函数从FRAM中读取太敏安装矩阵，该值会存入FR_MATSUNS
*/
void LOS_FVAR_GetMATSUNSFromFRAM()
{
    static uint8_t KEY_Bytes[68]; //存放解码后的数据
    static int ret_dcd = 0;
    LOS_W25Q64_ReadData(ADDR_FR_MATSUNS, KEY_Bytes, 68);
    ret_dcd = decode_rs(KEY_Bytes, NULL, 0, NN - NROOTS - 36);
    if(ret_dcd >= 0 && ret_dcd <= 8) //解码成功
    {
        memcpy(FR_MATSUNS, KEY_Bytes, 36);
        FR_MATSUNS_SEL = FROM_FRAM;
    }
    else //解码失败，则用默认值
    {
        FR_MATSUNS[0] = 0;
        FR_MATSUNS[1] = -1;
        FR_MATSUNS[2] = 0;
        FR_MATSUNS[3] = 0;
        FR_MATSUNS[4] = 0;
        FR_MATSUNS[5] = 1;
        FR_MATSUNS[6] = -1;
        FR_MATSUNS[7] = 0;
        FR_MATSUNS[8] = 0;
        FR_MATSUNS_SEL = FROM_DEFAULT;
    }
}

/** @fn void LOS_FVAR_ModifyMATMAGME(float* value)
*   @brief 修改FRAM中FR_MATMAGME磁强计安装矩阵的值
*   @param[in] value 指向上注安装矩阵缓冲区的指针
*   @note 
*/
void LOS_FVAR_ModifyMATMAGME(float* value)
{
    static uint8_t KEY_Bytes[68]; //存放编码后的数据
    static int ret_dcd = 0;

    LOS_W25Q64_SectorErase(ADDR_FR_MATMAGME);
    memcpy(KEY_Bytes, value, 36);
    encode_rs(KEY_Bytes, &KEY_Bytes[36], NN - NROOTS - 36);
    LOS_W25Q64_PageWrite(ADDR_FR_MATMAGME, KEY_Bytes, 36 + NROOTS);
    LOS_FVAR_GetMATMAGMEFromFRAM();
}

/** @fn void LOS_FVAR_GetMATMAGMEFromFRAM()
*   @brief 读取FRAM中预存的磁强计安装矩阵
*   @note 该函数从FRAM中读取磁强计安装矩阵，该值会存入FR_MATMAGME
*/
void LOS_FVAR_GetMATMAGMEFromFRAM()
{
    static uint8_t KEY_Bytes[68]; //存放解码后的数据
    static int ret_dcd = 0;
    LOS_W25Q64_ReadData(ADDR_FR_MATMAGME, KEY_Bytes, 68);
    ret_dcd = decode_rs(KEY_Bytes, NULL, 0, NN - NROOTS - 36);
    if(ret_dcd >= 0 && ret_dcd <= 8) //解码成功
    {
        memcpy(FR_MATMAGME, KEY_Bytes, 36);
        FR_MATMAGME_SEL = FROM_FRAM;
    }
    else //解码失败，则用默认值
    {
        FR_MATMAGME[0] = 0;
        FR_MATMAGME[1] = 0;
        FR_MATMAGME[2] = 1;
        FR_MATMAGME[3] = -1;
        FR_MATMAGME[4] = 0;
        FR_MATMAGME[5] = 0;
        FR_MATMAGME[6] = 0;
        FR_MATMAGME[7] = -1;
        FR_MATMAGME[8] = 0;
        FR_MATMAGME_SEL = FROM_DEFAULT;
    }
}

/** @fn void LOS_FVAR_ModifyMQSSY(float* value)
*   @brief 修改FRAM中FR_MQSSY星敏Y安装四元数的值
*   @param[in] value 指向上注安装四元数缓冲区的指针
*   @note 
*/
void LOS_FVAR_ModifyMQSSY(float* value)
{
    static uint8_t KEY_Bytes[48]; //存放编码后的数据
    static int ret_dcd = 0;

    LOS_W25Q64_SectorErase(ADDR_FR_MQSSY);
    memcpy(KEY_Bytes, value, 16);
    encode_rs(KEY_Bytes, &KEY_Bytes[16], NN - NROOTS - 16);
    LOS_W25Q64_PageWrite(ADDR_FR_MQSSY, KEY_Bytes, 16 + NROOTS);
    LOS_FVAR_GetMQSSYFromFRAM();
}

/** @fn void LOS_FVAR_GetMQSSYFromFRAM()
*   @brief 读取FRAM中预存的星敏Y安装四元数
*   @note 该函数从FRAM中读取星敏Y安装四元数，该值会存入FR_MQSSY
*/
void LOS_FVAR_GetMQSSYFromFRAM()
{
    static uint8_t KEY_Bytes[48]; //存放解码后的数据
    static int ret_dcd = 0;
    LOS_W25Q64_ReadData(ADDR_FR_MQSSY, KEY_Bytes, 48);
    ret_dcd = decode_rs(KEY_Bytes, NULL, 0, NN - NROOTS - 16);
    if(ret_dcd >= 0 && ret_dcd <= 8) //解码成功
    {
        memcpy(FR_MQSSY, KEY_Bytes, 16);
        FR_MQSSY_SEL = FROM_FRAM;
    }
    else //解码失败，则用默认值
    {
        FR_MQSSY[0] = 0;
        FR_MQSSY[1] = 0;
        FR_MQSSY[2] = -0.707107;
        FR_MQSSY[3] = 0.707107;
        FR_MQSSY_SEL = FROM_DEFAULT;
    }
}

/** @fn void LOS_FVAR_ModifyMQSSZ(float* value)
*   @brief 修改FRAM中FR_MQSSZ星敏Z安装四元数的值
*   @param[in] value 指向上注安装四元数缓冲区的指针
*   @note 
*/
void LOS_FVAR_ModifyMQSSZ(float* value)
{
    static uint8_t KEY_Bytes[48]; //存放编码后的数据
    static int ret_dcd = 0;

    LOS_W25Q64_SectorErase(ADDR_FR_MQSSZ);
    memcpy(KEY_Bytes, value, 16);
    encode_rs(KEY_Bytes, &KEY_Bytes[16], NN - NROOTS - 16);
    LOS_W25Q64_PageWrite(ADDR_FR_MQSSZ, KEY_Bytes, 16 + NROOTS);
    LOS_FVAR_GetMQSSZFromFRAM();
}

/** @fn void LOS_FVAR_GetMQSSZFromFRAM()
*   @brief 读取FRAM中预存的星敏Z安装四元数
*   @note 该函数从FRAM中读取星敏Z安装四元数，该值会存入FR_MQSSZ
*/
void LOS_FVAR_GetMQSSZFromFRAM()
{
    static uint8_t KEY_Bytes[48]; //存放解码后的数据
    static int ret_dcd = 0;
    LOS_W25Q64_ReadData(ADDR_FR_MQSSZ, KEY_Bytes, 48);
    ret_dcd = decode_rs(KEY_Bytes, NULL, 0, NN - NROOTS - 16);
    if(ret_dcd >= 0 && ret_dcd <= 8) //解码成功
    {
        memcpy(FR_MQSSZ, KEY_Bytes, 16);
        FR_MQSSZ_SEL = FROM_FRAM;
    }
    else //解码失败，则用默认值
    {
        FR_MQSSZ[0] = 0;
        FR_MQSSZ[1] = 0;
        FR_MQSSZ[2] = 1;
        FR_MQSSZ[3] = 0;
        FR_MQSSZ_SEL = FROM_DEFAULT;
    }
}

/** @fn void LOS_FVAR_ModifyMGTMAX(float* value)
*   @brief 修改FRAM中FR_MGTMAX磁力矩器最大磁矩
*   @param[in] value 指向模式切换阈值缓冲区的指针
*   @note 
*/
void LOS_FVAR_ModifyMGTMAX(float* value)
{
    static uint8_t KEY_Bytes[56]; //存放编码后的数据
    static int ret_dcd = 0;

    LOS_W25Q64_SectorErase(ADDR_FR_MGTMAX);
    memcpy(KEY_Bytes, value, 24);
    encode_rs(KEY_Bytes, &KEY_Bytes[24], NN - NROOTS - 24);
    LOS_W25Q64_PageWrite(ADDR_FR_MGTMAX, KEY_Bytes, 24 + NROOTS);
    LOS_FVAR_GetMGTMAXFromFRAM();
}

/** @fn void LOS_FVAR_GetMGTMAXFromFRAM()
*   @brief 读取FRAM中预存的磁力矩器最大磁矩
*   @note 该函数从FRAM中读取磁力矩器最大磁矩，该值会存入FR_MGTMAX
*/
void LOS_FVAR_GetMGTMAXFromFRAM()
{
    static uint8_t KEY_Bytes[56]; //存放解码后的数据
    static int ret_dcd = 0;
    LOS_W25Q64_ReadData(ADDR_FR_MGTMAX, KEY_Bytes, 56);
    ret_dcd = decode_rs(KEY_Bytes, NULL, 0, NN - NROOTS - 24);
    if(ret_dcd >= 0 && ret_dcd <= 8) //解码成功
    {
        memcpy(FR_MGTMAX, KEY_Bytes, 24);
        FR_MGTMAX_SEL = FROM_FRAM;
    }
    else //解码失败，则用默认值
    {
        FR_MGTMAX[0] = 0.2732;
        FR_MGTMAX[1] = 0.3811;
        FR_MGTMAX[2] = -0.3563;
        FR_MGTMAX[3] = -0.3149;
        FR_MGTMAX[4] = -0.1365;
        FR_MGTMAX[5] = 0.5;
        FR_MGTMAX_SEL = FROM_DEFAULT;
    }
}

/** @fn void LOS_FVAR_ModifyMCTR(float* value)
*   @brief 修改FRAM中FR_MCTR模式切换阈值
*   @param[in] value 指向模式切换阈值缓冲区的指针
*   @note 
*/
void LOS_FVAR_ModifyMCTR(float value, uint32_t index)
{
    static uint8_t KEY_Bytes[112]; //存放编码后的数据
    static int ret_dcd = 0;
    static float fbuf = 0;

    fbuf = value;
    //先获取一下FRAM里的值
    LOS_FVAR_GetMCTRFromFRAM();
    if (FR_MCTR_SEL == FROM_FRAM) //FRAM里有初始值,先把初始值存下来
    {
        memcpy(KEY_Bytes, FR_MCTR, 80);
    }//FRAM里本身没数就先不管了，用程序里的默认值

    memcpy(&KEY_Bytes[index*4], &fbuf, 4); //修改需要改的值
    LOS_W25Q64_SectorErase(ADDR_FR_MCTR);
    encode_rs(KEY_Bytes, &KEY_Bytes[80], NN - NROOTS - 80);
    LOS_W25Q64_PageWrite(ADDR_FR_MCTR, KEY_Bytes, 80 + NROOTS);
    LOS_FVAR_GetMCTRFromFRAM();
}

/** @fn void LOS_FVAR_GetMCTRFromFRAM()
*   @brief 读取FRAM中预存的模式切换阈值
*   @note 该函数从FRAM中读取模式切换阈值，该值会存入FR_MCTR
*/
void LOS_FVAR_GetMCTRFromFRAM()
{
    static uint8_t KEY_Bytes[112]; //存放解码后的数据
    static int ret_dcd = 0;
    LOS_W25Q64_ReadData(ADDR_FR_MCTR, KEY_Bytes, 112);
    ret_dcd = decode_rs(KEY_Bytes, NULL, 0, NN - NROOTS - 80);
    if(ret_dcd >= 0 && ret_dcd <= 8) //解码成功
    {
        memcpy(FR_MCTR, KEY_Bytes, 80);
        FR_MCTR_SEL = FROM_FRAM;
    }
    else //解码失败，则用默认值
    {
        FR_MCTR[0] = 960;  //单轴转三轴姿态有效计数上限
        FR_MCTR[1] = 15000;  //太敏超视场及太阳角大于60度计数上限
        FR_MCTR[2] = 240;  //实现对日后转为三轴对日间隔
        FR_MCTR[3] = 0.02;  //整星角动量开始消旋阈值（上限）
        FR_MCTR[4] = 7500;  //关飞轮进消旋转速
        FR_MCTR[5] = 5;  //整星角速度结束消旋阈值（下限）
        FR_MCTR[6] = 3000;  //飞轮卸载阈值角动量（转速）
        FR_MCTR[7] = 1500;  //飞轮标称角动量（转速）
        FR_MCTR[8] = 11.6;  //母线电压阈值11.6V
        FR_MCTR[9] = 11;  //母线电压阈值11V
        FR_MCTR[10] = 10.4;  //母线电压阈值10.4V
        FR_MCTR[11] = 1200;  //载荷工作时长上限
        FR_MCTR[12] = 240; //母线电压计数阈值
        FR_MCTR[13] = 25; //停控角速度阈值
        FR_MCTR[14] = -0.7166;   //太阳矢量X（惯性系）
        FR_MCTR[15] = -0.6400;   //太阳矢量Y（惯性系）
        FR_MCTR[16] = -0.2774;   //太阳矢量Z（惯性系）
        FR_MCTR[17] = 0;
        FR_MCTR[18] = 0;
        FR_MCTR[19] = 0;
        FR_MCTR_SEL = FROM_DEFAULT;
    }
}
 
/** @fn void LOS_FVAR_ModifyTKMAXCNT(uint32_t maxcnt)
*   @brief 修改FRAM中的TKMAXCNT值
*   @param[in] maxcnt 最大重复烧绳的次数
*   @note 该函数除了会改变FRAM中的TKMAXCNT，还会更新FR_TKMAXCNT的值
*/
void LOS_FVAR_ModifyTKMAXCNT(uint32_t maxcnt)
{
    static uint8_t TK_Bytes[36]; //存放编码后的数据
    static int ret_dcd = 0;
    uint32_t buf = maxcnt;

    LOS_W25Q64S_SectorErase(ADDR_FR_TKMAXCNT);
    memcpy(TK_Bytes, &buf, 4);
    encode_rs(TK_Bytes, &TK_Bytes[4], NN - NROOTS - 4);
    LOS_W25Q64S_PageWrite(ADDR_FR_TKMAXCNT, TK_Bytes, 4 + NROOTS);
    LOS_FVAR_GetTKMAXCNTFromFRAM();
}

/** @fn uint32_t LOS_FVAR_GetTKMAXCNTFromFRAM()
*   @brief 读取FRAM中预存的TKMAXCNT值
*   @note 该函数从FRAM中读取TKMAXCNT值，该值会存入FR_TKMAXCNT值，并通过返回值传递
*/
uint32_t LOS_FVAR_GetTKMAXCNTFromFRAM()
{
    static uint8_t TK_Bytes[36]; //存放解码后的数据
    LOS_W25Q64S_ReadData(ADDR_FR_TKMAXCNT, TK_Bytes, 36);
    if(decode_rs(TK_Bytes, NULL, 0, NN - NROOTS - 4) >= 0) //解码成功
    {
        memcpy(&FR_TKMAXCNT, TK_Bytes, 4);
        FR_TKMAXCNT_SEL = FROM_FRAM;
    }
    else //解码失败
    {
        FR_TKMAXCNT = 3;
        FR_TKMAXCNT_SEL = FROM_DEFAULT;
    }
    return FR_TKMAXCNT;
}

/** @fn void LOS_FVAR_ModifyTKDUR(uint32_t maxcnt)
*   @brief 修改FRAM中的TKDUR值
*   @param[in] maxcnt 烧绳后空闲周期
*   @note 该函数除了会改变FRAM中的TKDUR，还会更新FR_TKDUR的值
*/
void LOS_FVAR_ModifyTKDUR(uint32_t maxcnt)
{
    static uint8_t TK_Bytes[36]; //存放编码后的数据
    static int ret_dcd = 0;
    uint32_t buf = maxcnt;

    LOS_W25Q64S_SectorErase(ADDR_FR_TKDUR);
    memcpy(TK_Bytes, &buf, 4);
    encode_rs(TK_Bytes, &TK_Bytes[4], NN - NROOTS - 4);
    LOS_W25Q64S_PageWrite(ADDR_FR_TKDUR, TK_Bytes, 4 + NROOTS);
    LOS_FVAR_GetTKDURFromFRAM();
}

/** @fn uint32_t LOS_FVAR_GetTKDURFromFRAM()
*   @brief 读取FRAM中预存的TKDUR值
*   @note 该函数从FRAM中读取TKDUR值，该值会存入FR_TKDUR值，并通过返回值传递
*/
uint32_t LOS_FVAR_GetTKDURFromFRAM()
{
    static uint8_t TK_Bytes[36]; //存放解码后的数据
    LOS_W25Q64S_ReadData(ADDR_FR_TKDUR, TK_Bytes, 36);
    if(decode_rs(TK_Bytes, NULL, 0, NN - NROOTS - 4) >= 0) //解码成功
    {
        memcpy(&FR_TKDUR, TK_Bytes, 4);
        FR_TKDUR_SEL = FROM_FRAM;
    }
    else //解码失败
    {
        FR_TKDUR = 1;
        FR_TKDUR_SEL = FROM_DEFAULT;
    }
    return FR_TKDUR;
}

/** @fn void LOS_FVAR_ModifyGPSAUTO(uint32_t key)
*   @brief 修改FRAM中的GPSAUTO值
*   @param[in] key 使能密钥，自然也是0XABED5CFA
*   @note 该函数除了会改变FRAM中的GPSAUTO，还会更新FR_GPSAUTO的值
*/
void LOS_FVAR_ModifyGPSAUTO(uint32_t key)
{
    static uint8_t TK_Bytes[36]; //存放编码后的数据
    static int ret_dcd = 0;
    uint32_t buf = key;

    LOS_W25Q64S_SectorErase(ADDR_FR_GPSAUTO);
    memcpy(TK_Bytes, &buf, 4);
    encode_rs(TK_Bytes, &TK_Bytes[4], NN - NROOTS - 4);
    LOS_W25Q64S_PageWrite(ADDR_FR_GPSAUTO, TK_Bytes, 4 + NROOTS);
    LOS_FVAR_GetGPSAUTOFromFRAM();
}

/** @fn uint32_t LOS_FVAR_GetGPSAUTOFromFRAM()
*   @brief 读取FRAM中预存的GPSAUTO值
*   @note 该函数从FRAM中读取GPSAUTO值，该值会存入FR_GPSAUTO值，并通过返回值传递
*/
uint32_t LOS_FVAR_GetGPSAUTOFromFRAM()
{
    static uint8_t TK_Bytes[36]; //存放解码后的数据
    LOS_W25Q64S_ReadData(ADDR_FR_GPSAUTO, TK_Bytes, 36);
    if(decode_rs(TK_Bytes, NULL, 0, NN - NROOTS - 4) >= 0) //解码成功
    {
        memcpy(&FR_GPSAUTO, TK_Bytes, 4);
        FR_GPSAUTO_SEL = FROM_FRAM;
    }
    else //解码失败
    {
        FR_GPSAUTO = 0XABED5CFA;
        FR_GPSAUTO_SEL = FROM_DEFAULT;
    }
    return FR_GPSAUTO;
}

/** @fn void LOS_FVAR_ModifyMAGCOMP(float* value)
*   @brief 修改FRAM中FR_MAGCOMP磁强计补偿值
*   @param[in] value 指向上注磁强计补偿值缓冲区的指针
*   @note 
*/
void LOS_FVAR_ModifyMAGCOMP(float* value)
{
    static uint8_t KEY_Bytes[44]; //存放编码后的数据
    static int ret_dcd = 0;
    LOS_W25Q64_SectorErase(ADDR_FR_MAGCOMP);
    memcpy(KEY_Bytes, value, 12);
    encode_rs(KEY_Bytes, &KEY_Bytes[12], NN - NROOTS - 12);
    LOS_W25Q64_PageWrite(ADDR_FR_MAGCOMP, KEY_Bytes, 12 + NROOTS);
    LOS_FVAR_GetMAGCOMPFromFRAM();
}

/** @fn void LOS_FVAR_GetMAGCOMPFromFRAM()
*   @brief 读取FRAM中预存的磁强计补偿值MAGCOMP
*   @note 该函数从FRAM中读取磁强计补偿值MAGCOMP，该值会存入FR_MAGCOMP
*/
void LOS_FVAR_GetMAGCOMPFromFRAM()
{
    static uint8_t KEY_Bytes[44]; //存放解码后的数据
    static int ret_dcd = 0;
    LOS_W25Q64_ReadData(ADDR_FR_MAGCOMP, KEY_Bytes, 44);
    ret_dcd = decode_rs(KEY_Bytes, NULL, 0, NN - NROOTS - 12);
    if(ret_dcd >= 0 && ret_dcd <= 4) //解码成功
    {
        memcpy(FR_MAGCOMP, KEY_Bytes, 12);
        FR_MAGCOMP_SEL = FROM_FRAM;
    }
    else //解码失败，则用默认值
    {
        FR_MAGCOMP[0] = 0;
        FR_MAGCOMP[1] = 0;
        FR_MAGCOMP[2] = 0;
        FR_MAGCOMP_SEL = FROM_DEFAULT;
    }
}

/** @fn void LOS_FVAR_ModifyDTAUTO(float* value)
*   @brief 修改FRAM中FR_DTAUTO自动开数传阈值
*   @param[in] value 指向上注自动开数传阈值的指针
*   @note 
*/
void LOS_FVAR_ModifyDTAUTO(uint32_t* value)
{
    static uint8_t KEY_Bytes[40]; //存放编码后的数据
    static int ret_dcd = 0;
    LOS_W25Q64_SectorErase(ADDR_FR_DTAUTO);
    memcpy(KEY_Bytes, value, 8);
    encode_rs(KEY_Bytes, &KEY_Bytes[8], NN - NROOTS - 8);
    LOS_W25Q64_PageWrite(ADDR_FR_DTAUTO, KEY_Bytes, 8 + NROOTS);
    LOS_FVAR_GetDTAUTOFromFRAM();
}

/** @fn void LOS_FVAR_GetDTAUTOFromFRAM()
*   @brief 读取FRAM中预存的自动开数传阈值DTAUTO
*   @note 该函数从FRAM中读取自动开数传阈值DTAUTO，该值会存入FR_DTAUTO
*/
void LOS_FVAR_GetDTAUTOFromFRAM()
{
    static uint8_t KEY_Bytes[40]; //存放解码后的数据
    static int ret_dcd = 0;
    LOS_W25Q64_ReadData(ADDR_FR_DTAUTO, KEY_Bytes, 40);
    ret_dcd = decode_rs(KEY_Bytes, NULL, 0, NN - NROOTS - 8);
    if(ret_dcd >= 0 && ret_dcd <= 4) //解码成功
    {
        memcpy(FR_DTAUTO, KEY_Bytes, 8);
        FR_DTAUTO_SEL = FROM_FRAM;
    }
    else //解码失败，则用默认值
    {
        FR_DTAUTO[0] = 43200;
        FR_DTAUTO[1] = 11300;
        FR_DTAUTO_SEL = FROM_DEFAULT;
    }
}